package com.binarysoft.cmdhandler.common.mulconnpool;

import java.sql.Connection;
import java.util.Collection;
import java.util.Map;
import java.util.StringTokenizer;

import com.binarysoft.service.common.multiconnpool.MultipleConnectionPoolService;

import common.framework.command.handler.AbstractCommandHandler;
import common.framework.command.helper.CommandHelper;
import common.framework.command.server.Terminal;
import common.framework.dsb.annotation.DSBCmd;
import common.framework.dsb.client.DefaultServiceFactory;
import common.framework.dsb.client.ServiceFactory;

@DSBCmd("db")
public class ShowMultiConnPoolCmdHandler extends AbstractCommandHandler {

	@Override
	public void handle(String args, Terminal terminal) throws Exception {
		terminal.println("");
		StringTokenizer stier = new StringTokenizer(args);
		int count = stier.countTokens();
		if (count < 2) {
			showOptions(terminal);
			terminal.println("");
			return;
		}
		stier.nextToken();
		String cmd = stier.nextToken();

		if ("ls".equalsIgnoreCase(cmd) && count == 2) {
			showPools(terminal);
		} else if ("add".equalsIgnoreCase(cmd) && count == 3) {
			String poolFileName = stier.nextToken();
			addPools(terminal, poolFileName);
		} else if ("conn".equalsIgnoreCase(cmd) && count == 2) {
			showConnections(terminal);
		} else if ("conn".equalsIgnoreCase(cmd) && count == 3) {
			String poolname = stier.nextToken();
			showConnections(terminal, poolname);
		} else if ("stacktrace".equalsIgnoreCase(cmd)) {
			showStackTrace(terminal);
		} else {
			showOptions(terminal);
		}
		terminal.println("");
	}

	private void showOptions(Terminal terminal) throws Exception {
		terminal.println(" db ls                         --show all pool names");
		terminal.println(" db add <poole_file_name>      --add new pools from config file");
		terminal.println(" db conn                       --show all pool's connectons status");
		terminal.println(" db conn <poolname>            --show the specified pool's connections status");
		terminal.println(" db stacktrace                 --show all unclosed connection call stack trace");
	}

	private void showStackTrace(Terminal terminal) throws Exception {
		ServiceFactory serviceFactory = new DefaultServiceFactory();
		MultipleConnectionPoolService multipleConnectionPoolService = serviceFactory.lookup("DSB/MultipleConnectionPoolService");
		Map<Connection, String> result = multipleConnectionPoolService.getStackTrace();
		int num = 0;
		for (Map.Entry<Connection, String> entry : result.entrySet()) {
			Connection conn = entry.getKey();
			boolean closed = conn.isClosed();
			if (!closed) {
				num++;
				String trace = entry.getValue();
				terminal.println("<--------------------------------------------------------->");
				terminal.println("name: " + conn.toString() + " closed: " + closed);
				terminal.println("stack trace:");
				terminal.println(trace);
			}
		}
		terminal.println(num + " unclosed connection(s) was found.");
	}

	private void addPools(Terminal terminal, String poolFileName) throws Exception {
		ServiceFactory serviceFactory = new DefaultServiceFactory();
		MultipleConnectionPoolService multipleConnectionPoolService = serviceFactory.lookup("DSB/MultipleConnectionPoolService");
		multipleConnectionPoolService.loadPoolConfig(poolFileName);
		terminal.println("");
		terminal.println("  pool(s) has been added success.");
		terminal.println("");
	}

	private void showPools(Terminal terminal) throws Exception {
		ServiceFactory serviceFactory = new DefaultServiceFactory();
		MultipleConnectionPoolService multipleConnectionPoolService = serviceFactory.lookup("DSB/MultipleConnectionPoolService");
		Collection<String> pools = multipleConnectionPoolService.listPools();
		for (String poolname : pools) {
			terminal.println("  " + poolname);
		}
		terminal.println("");
		terminal.println("  " + pools.size() + " pool(s) was found.");
		terminal.println("");
	}

	private void showConnections(Terminal terminal) throws Exception {
		ServiceFactory serviceFactory = new DefaultServiceFactory();
		MultipleConnectionPoolService multipleConnectionPoolService = serviceFactory.lookup("DSB/MultipleConnectionPoolService");

		String[] tableHAD = { "Pool Name", "initial pool size", "Connections", "Idle connections", "Busy connections" };
		String[] tableGAP = { "---------", "-----------------", "-----------", "----------------", "----------------" };
		int[] format = { 30, 20, 20, 20, 20 };
		terminal.println(CommandHelper.format(tableHAD, format));
		terminal.println(CommandHelper.format(tableGAP, format));
		Collection<String> pools = multipleConnectionPoolService.listPools();
		for (String poolname : pools) {
			int connectons = multipleConnectionPoolService.getNumConnections(poolname);
			int initpoolsize = multipleConnectionPoolService.getInitialPoolSize(poolname);
			int idleconnections = multipleConnectionPoolService.getNumIdleConnections(poolname);
			int busyconnections = multipleConnectionPoolService.getNumBusyConnections(poolname);
			Object[] row = { poolname, initpoolsize, connectons, idleconnections, busyconnections };
			terminal.println(CommandHelper.format(row, format));
		}
		terminal.println("");
	}

	private void showConnections(Terminal terminal, String poolname) throws Exception {
		ServiceFactory serviceFactory = new DefaultServiceFactory();
		MultipleConnectionPoolService multipleConnectionPoolService = serviceFactory.lookup("DSB/MultipleConnectionPoolService");

		String[] tableHAD = { "Pool Name", "initial pool size", "Connections", "Idle connections", "Busy connections" };
		String[] tableGAP = { "---------", "-----------------", "-----------", "----------------", "----------------" };
		int[] format = { 30, 20, 20, 20, 20 };
		terminal.println(CommandHelper.format(tableHAD, format));
		terminal.println(CommandHelper.format(tableGAP, format));
		Collection<String> pools = multipleConnectionPoolService.listPools();
		for (String pname : pools) {
			if (pname.equalsIgnoreCase(poolname)) {
				int connectons = multipleConnectionPoolService.getNumConnections(poolname);
				int initpoolsize = multipleConnectionPoolService.getInitialPoolSize(poolname);
				int idleconnections = multipleConnectionPoolService.getNumIdleConnections(poolname);
				int busyconnections = multipleConnectionPoolService.getNumBusyConnections(poolname);
				Object[] row = { poolname, initpoolsize, connectons, idleconnections, busyconnections };
				terminal.println(CommandHelper.format(row, format));
			}
		}
		terminal.println("");
	}
}
